package com.learning.rpc.remoting.netty;

import com.learning.rpc.remoting.Codec;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;

import java.util.List;

/**
 * ClassName: NettyCodec
 * Description: 编解码器处理器
 * 1. 接收端：把请求中的网络字节数据，转成 Java 对象
 * 2. 发送端：发送的数据以特定的协议格式发送
 * ---------
 * Date: 2022/5/10 22:54 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
public class NettyCodec extends ChannelDuplexHandler {

    private Codec codec;

    public NettyCodec(Codec codec) {
        this.codec = codec;
    }

    /**
     * 入栈事件（收到数据，请求/响应）
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 解码
        // 1. 读取数据
        ByteBuf data = (ByteBuf) msg;
        byte[] dataBytes = new byte[data.readableBytes()];
        data.readBytes(dataBytes);

        // 2. 格式转换 —— Java对象
        final List<Object> out = codec.decode(dataBytes);

        // 3. 处理器继续处理（处理器向后传递）
        for (Object o : out) {
            ctx.fireChannelRead(o);
        }
    }

    /**
     * 编码
     *
     * @param ctx
     * @param msg
     * @param promise
     * @throws Exception
     */
    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        final byte[] encode = codec.encode(msg);
        final ByteBuf byteBuf = Unpooled.wrappedBuffer(encode);
        super.write(ctx, byteBuf, promise);
    }
}
